package burubaka.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import net.arnx.jsonic.JSON;

import org.slim3.datastore.Datastore;
import org.slim3.util.BeanUtil;

import burubaka.BurubakaConstants;
import burubaka.common.BurubakaUtil;
import burubaka.common.KeibaNiftyUtil;
import burubaka.common.NetkeibaUtil;
import burubaka.meta.RaceInfoMeta;
import burubaka.model.PreRaceInfo;
import burubaka.model.RaceInfo;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;

/**
 * @author tk
 * 
 */
public class RaceInfoService {

	private static final Logger log = Logger.getLogger(RaceInfoService.class.getName());

	private RaceInfoMeta meta = new RaceInfoMeta();

	/**
	 * レース情報を取得する
	 * 
	 * @param preRaceInfo
	 * @return
	 * @throws Exception
	 */
	public RaceInfo getRaceInfo(PreRaceInfo preRaceInfo) throws Exception {
		if (BurubakaUtil.isLocal(preRaceInfo.getDistrictClass())) {
			return getLocalRaceInfo(preRaceInfo);
		}

		return getCenterRaceInfo(preRaceInfo);
	}

	/**
	 * 中央レース情報を取得する
	 * 
	 * @param preRaceInfo
	 * @return
	 * @throws Exception
	 */
	private RaceInfo getCenterRaceInfo(PreRaceInfo preRaceInfo) throws Exception {

		String nameArea = KeibaNiftyUtil.getTopPageRaceNameArea(KeibaNiftyUtil.getTopPageStr());
		String url = KeibaNiftyUtil.getRaceUrl(preRaceInfo.getRaceName(), nameArea);
		log.fine(url);
		if (url == null) {
			log.info("中央ＵＲＬが取得できませんした");
			return null;
		}

		String text = KeibaNiftyUtil.getURLText(url, BurubakaConstants.BASE_URL_NOMI);
		RaceInfo raceInfo = KeibaNiftyUtil.getRaceInfo(text, url);
		return raceInfo;
	}

	/**
	 * 中央レース情報を取得する
	 * 
	 * @param preRaceInfo
	 * @return
	 * @throws Exception
	 */
	private RaceInfo getLocalRaceInfo(PreRaceInfo preRaceInfo) throws Exception {

		String nameArea = NetkeibaUtil.getTopPageRaceNameArea(NetkeibaUtil.getTopPageStr());
		if (nameArea == null) {
			log.info("レース名が取得できませんした");
			return null;
		}
		String url = NetkeibaUtil.getRaceUrl(preRaceInfo.getRaceName(), nameArea);
		log.fine(url);
		if (url == null) {
			log.info("地方ＵＲＬが取得できませんした");
			return null;
		}

		String text = NetkeibaUtil.getURLText(url, BurubakaConstants.BASE_URL_RC_LOCAL);
		RaceInfo raceInfo = NetkeibaUtil.getRaceInfo(text, url);
		return raceInfo;
	}

	/**
	 * @param url
	 * @return URLText
	 * @throws Exception
	 */
	public String getURLNomiText(String url) throws Exception {
		return KeibaNiftyUtil.getURLText(url, BurubakaConstants.BASE_URL_NOMI);
	}

	/**
	 * @param text
	 * @param url
	 * @return RaceInfo
	 * @throws Exception
	 */
	public RaceInfo getRaceInfo(String text, String url) throws Exception {
		String raceInfoText = BurubakaUtil.substring("<div id=\"resultTtl\" class=\"noBg\">", "</div>", text);
		String raceDate = BurubakaUtil.substring("<p class=\"date\">", "</p>", raceInfoText);
		log.info(raceDate);
		// レース情報
		RaceInfo raceInfo = this.findByRaceDate(raceDate);
		// レース情報取得
		if (raceInfo == null) {
			raceInfo = KeibaNiftyUtil.getRaceInfo(url, raceInfoText, raceDate);
		}
		return raceInfo;
	}

	/**
	 * キー検索
	 * 
	 * @param key
	 * @return RaceInfo
	 */
	public RaceInfo findByKey(Key key) {
		return Datastore.query(RaceInfo.class, key).asSingle();
	}

	/**
	 * キー検索
	 * 
	 * @param key
	 * @return RaceInfo
	 */
	public String findJsonByKey(Key key) {
		return meta.modelToJson(Datastore.query(RaceInfo.class, key).asSingle());
	}

	/**
	 * レース日付で検索
	 * 
	 * @param raceDate
	 * @return RaceInfo
	 */
	public RaceInfo getRaceInfoByRaceDate(String raceDate) {
		return this.findByRaceDate(raceDate);
	}

	/**
	 * レース日付で検索
	 * 
	 * @param raceDate
	 * @return RaceInfo
	 */
	public RaceInfo findByRaceDate(String raceDate) {
		return Datastore.query(meta).filter(meta.raceDate.equal(raceDate)).asSingle();
	}

	/**
	 * 現在レース情報を取得
	 * 
	 * @return RaceInfo
	 */
	public RaceInfo getCurrentRaceInfo() {
		return Datastore.query(meta).filter(meta.currentFlg.equal(BurubakaConstants.FLAG_ON)).asSingle();
	}

	/**
	 * 前回レース情報を取得
	 * 
	 * @return RaceInfo
	 */
	public RaceInfo getLastRaceInfo() {
		return Datastore.query(meta).filter(meta.currentFlg.equal(BurubakaConstants.FLAG_OFF)).sort(meta.raceDate.desc)
				.offset(0).limit(1).asSingle();
	}

	/**
	 * 現在レース情報を取得
	 * 
	 * @return RaceInfo
	 */
	public String getCurrentRaceForJSON() {
		RaceInfo raceInfo = this.getCurrentRaceInfo();
		if (raceInfo == null) {
			raceInfo = new RaceInfo();
		}
		return meta.modelToJson(raceInfo);
	}

	/**
	 * 全件検索
	 * 
	 * @return RaceInfoList
	 */
	public List<RaceInfo> findAll() {
		return Datastore.query(meta).sort(meta.raceDate.desc).asList();
	}

	/**
	 * 登録
	 * 
	 * @param input
	 * @param progress
	 * @return RaceInfo
	 */
	public RaceInfo regist(Map<String, Object> input, int progress) {
		log.info(input.toString());

		// Key key = JSON.decode((String)input.get("key"),Key.class);
		// log.info(key.toString());
		Map<String, Object> map = JSON.decode((String) input.get("raceInfo"), HashMap.class);
		log.info(map.toString());
		RaceInfo raceInfo = findByRaceDate((String) map.get("raceDate"));
		// RaceInfo raceInfo = findByRaceDate(key);
		if (raceInfo == null) {
			log.info("raceInfo is null");
			raceInfo = new RaceInfo();
		}
		BeanUtil.copy(map, raceInfo);
		raceInfo.setProgress(progress);
		raceInfo.setCurrentFlg(BurubakaConstants.FLAG_ON);
		Transaction tx = Datastore.beginTransaction();
		Datastore.put(raceInfo);
		tx.commit();
		return raceInfo;
	}

	/**
	 * 登録
	 * 
	 * @param input
	 * @param progress
	 * @return RaceInfo
	 */
	public RaceInfo regist(RaceInfo raceInfo) {
		Transaction tx = Datastore.beginTransaction();
		Datastore.put(raceInfo);
		tx.commit();
		return raceInfo;
	}

	/**
	 * 全削除
	 * 
	 * @param raceInfo
	 * @return RaceInfo
	 */
	public boolean deleteAll(RaceInfo raceInfo) {
		Transaction tx = Datastore.beginTransaction();
		Datastore.deleteAll(raceInfo.getKey());
		tx.commit();
		return true;
	}

}
